/*
 * Copyright 2009 BioTeam Inc
 * 
 * Licensed under License GNU LESSER GENERAL PUBLIC LICENSE version 3.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 * 
 * http://www.gnu.org/copyleft/lesser.html
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */
package net.bioteam.appweb.submit;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;

import net.bioteam.appweb.model.Parameter;
import net.bioteam.appweb.model.ParameterType;

public class MrBayesCommandLineGenerator implements CommandGenerator
{
	public static final String NAME="MRBAYES";
	public String getName()
	{
		return NAME;
	}

	 public boolean postProcessMPI()
	 {
		 return true;
	 }
	public String generateScript(ProgramValueBean bean, UnfinishedJob job) throws EvaluationException, CtrlException, IOException
	{

		if (getParamValue(bean, bean.getParameter("mb_contain_cmd")).equals("yes"))
		{
			
			String nexus_file = getParamValue(bean, bean.getParameter("nexus_file"));
			File file=new File(nexus_file);
			
			return "mb "+file.getName();
		}
		// #user input is good so far.
		File targetFile = new File(job.getWorkdir() + File.separator + "mrbayes.txt");
		Writer out = new BufferedWriter(new FileWriter(targetFile));
		out.write("begin mrbayes;\n");
		out.write("\tset autoclose=yes nowarn=yes;\n");
		String nexus_file = getParamValue(bean, bean.getParameter("nexus_file"));
		File file=new File(nexus_file);
		out.write("\texecute " + file.getName() + ";\n");

		//int ncpu = 8;

		// ###############the process order is important.
		// #----------------process lset
		String lsetparams[] = { "covarion", "parsmodel", "omegavar", "nucmodel", "nbetacat", "ngammacat", "nst", "code", "rates", "coding" };
		out.write(getCommandStr("lset", lsetparams, bean));

		// #-------------------prset
		String prsetparams[] = { "aamodelpr", "brlenspr", "codoncatfreqs", "covswitchpr", "extinctionpr", "ny98omega1pr", "ny98omega3pr", "m3omegapr", "omegapr", "pinvarpr", "ratepr", "ratecorrpr",
								"revmatpr", "sampleprob", "shapepr", "speciationpr", "symdirihyperpr", "statefreqpr", "thetapr", "topologypr", "tratiopr" };
		out.write(getCommandStr("prset", prsetparams, bean));
		// ----------------------------opts
		String optsparams[] = { "about", "acknowledgments", "charstat", "citations", "disclaimer", "help", "showmatrix", "showmodel", "showtree", "taxastat", "version" };
		for (String paramname : optsparams)
		{
			Parameter param = bean.getParameter(paramname);
			String value = getParamValue(bean, param);
			if (value!=null && value.equals("yes"))
				out.write("\t" + paramname + ";\n");
		}

		// ----------------------report
		String reportparams[] = { "rep_tratio", "rep_revmat", "rep_ratemult" };
		StringBuffer rsb = new StringBuffer();
		for (String paramname : reportparams)
		{
			Parameter param = bean.getParameter(paramname);
			String value = getParamValue(bean, param);
			if (value != null)
			{
				rsb.append(" ");
				rsb.append(paramname.substring(4) + "=" + value);
			}
		}
		if (rsb.length() > 0)
		{
			out.write("\treport" + rsb.toString() + ";\n");
		}

		// #group 8:--------------------process mcmc
		StringBuffer msb = new StringBuffer();
		String value = getParamValue(bean, bean.getParameter("mcmcp"));
		if (value.equals("yes"))
			msb.append("mcmcp");
		else
			msb.append("mcmc");
		String mcmcparams[] = { "burnin", "nchains", "ngen", "nperts", "printfreq", "samplefreq", "seed", "swapfreq", "temp", "reweight", "savebrlens", "startingtree" };
		String mcmcStr = getCommandStr(msb.toString(), mcmcparams, bean);
		if (mcmcStr.length() > 0)
		{
			out.write(mcmcStr);
		} else
		{
			out.write("\t" + msb.toString() + ";\n");
		}

		String nchainStr = getParamValue(bean, bean.getParameter("nchains"));

		int nchain = 0;
		if (nchainStr != null)
		{
			nchain = Integer.parseInt(nchainStr);
//			if (nchain < 16)
//			{
//				ncpu = nchain;
//			} else
//			{
//				ncpu = 16;
//			}
		} else
		{
			// TODO grep $nexus_file to find the nchains parameter
		}

		// #-----------------------process report
		String plotparams[] = { "doplot", "plot_burnin", "plot_param", "plot_match" };
		StringBuffer plotsb = new StringBuffer();
		for (String paramname : plotparams)
		{
			String paramvalue = getParamValue(bean, bean.getParameter(paramname));
			if (paramvalue != null)
			{
				if (paramname.equals("doplot"))
				{
					if (paramvalue.equals("yes"))
						plotsb.append(" ");
				} else if (paramname.equals("plot_burnin"))
				{
					plotsb.append(" burnin=" + paramvalue);

				} else if (paramname.equals("plot_param"))
				{
					plotsb.append(" parameter=" + paramvalue);
				} else if (paramname.equals("plot_match"))
				{
					plotsb.append(" match=" + paramvalue);
				}
			}
		}
		if (plotsb.length() > 0)
		{
			out.write("\tplot" + plotsb.toString() + ";\n");
		}

		// #----------------------------------sump
		//String sumpparams[] = { "dosump", "sump_burnin" };
		StringBuffer sumpsb = new StringBuffer();
		value = getParamValue(bean, bean.getParameter("dosump"));
		if (value!=null && value.equals("yes"))
			sumpsb.append(" filename=" + nexus_file);
		value = getParamValue(bean, bean.getParameter("sump_burnin"));
		if (value != null)
			sumpsb.append(" burnin=" + value);
		if (sumpsb.length() > 0)
			out.write("\tsump" + sumpsb.toString() + ";\n");

		// #----------------- sumt
		String sumtparams[] = { "dosumt", "sumt_burnin", "sumt_displaygeq", "sumt_contype", "sumt_showtreeprobs" };
		StringBuffer sumtsb = new StringBuffer();
		for (String paramname : sumtparams)
		{
			value = getParamValue(bean, bean.getParameter(paramname));
			if (value == null)
				continue;
			if (paramname.equals("dosumt"))
			{
				if (value.equals("yes"))
					sumtsb.append(" filename=" + nexus_file);
			} else
			{
				sumtsb.append(" ");
				sumtsb.append(paramname.substring(5) + "=" + value);
			}
		}
		if (sumtsb.length() > 0)
			out.write("\tsumt" + sumtsb.toString() + ";\n");

		// #--------------------comparetree
		StringBuffer cmptreesb = new StringBuffer();

		String cmptreeparams[] = { "filename1", "filename2", "outputname", "ctree_burnin" };
		for (String paramname : cmptreeparams)
		{
			value = getParamValue(bean, bean.getParameter(paramname));
			if (value == null)
				continue;
			if (paramname.equals("ctree_burnin"))
			{
				paramname = "burnin";
			}
			cmptreesb.append(" ");
			cmptreesb.append(paramname + "=" + value);
		}
		if (cmptreesb.length() > 0)
		{
			value = getParamValue(bean, bean.getParameter("ctree_nexus"));
			if (value != null && value.equals("yes"))
			{
				out.write("\tcomparetree filename1=" + nexus_file + ".t" + cmptreesb.toString() + ";\n");
			} else
			{
				out.write("\tcomparetree " + cmptreesb.toString() + ";\n");
			}
		}
		out.write("end;\n");
		out.close();
		return "mb mrbayes.txt";
	}

	private String getCommandStr(String command, String[] params, ProgramValueBean bean)
	{
		StringBuffer buf = new StringBuffer();
		for (String paramname : params)
		{
			Parameter param = bean.getParameter(paramname);
			String value = getParamValue(bean, param);
			if (value != null)
			{
				buf.append(" ");
				buf.append(paramname + "=" + value);
			}
		}
		if (buf.length() > 0)
		{
			return "\t" + command + buf.toString() + ";\n";
		} else
		{
			return "";
		}
	}

	protected String getParamValue(ProgramValueBean bean, Parameter param)
	{

		String value = bean.getValue(param.getName());
		String defaultValue = param.getDeaultValue();
		if (param.getType() == ParameterType.BooleanType)
		{
			if (value!=null && value.equals("1"))
				return "yes";
			else
				return "no";
		} else
		{
			if (value != null && defaultValue != null && value.equals(defaultValue))
				return null;
			else
				return value;
		}

	}

}
